package com.example.easyscript.utils.recognization;

import org.opencv.core.*;
import org.opencv.features2d.*;
import org.opencv.highgui.Highgui;

import java.util.LinkedList;
import java.util.List;

public class RecognizationSURF {

    public static Boolean judgeTemplateIsInSource(String templatePath, String sourcePath, float confidence,Integer passCount) {
        System.loadLibrary(Core.NATIVE_LIBRARY_NAME) ;
        Mat templateImage = Highgui.imread(templatePath, Highgui.CV_LOAD_IMAGE_COLOR);
        Mat originalImage = Highgui.imread(sourcePath, Highgui.CV_LOAD_IMAGE_COLOR);
        MatOfKeyPoint templateKeyPoints = new MatOfKeyPoint();
        //指定特征点算法SURF
        FeatureDetector featureDetector = FeatureDetector.create(FeatureDetector.SURF);
        //获取模板图的特征点
        featureDetector.detect(templateImage, templateKeyPoints);
        //提取模板图的特征点
        MatOfKeyPoint templateDescriptors = new MatOfKeyPoint();
        DescriptorExtractor descriptorExtractor = DescriptorExtractor.create(DescriptorExtractor.SURF);
        descriptorExtractor.compute(templateImage, templateKeyPoints, templateDescriptors);

        //获取原图的特征点
        MatOfKeyPoint originalKeyPoints = new MatOfKeyPoint();
        MatOfKeyPoint originalDescriptors = new MatOfKeyPoint();
        featureDetector.detect(originalImage, originalKeyPoints);
        descriptorExtractor.compute(originalImage, originalKeyPoints, originalDescriptors);

        List<MatOfDMatch> matches = new LinkedList();
        DescriptorMatcher descriptorMatcher = DescriptorMatcher.create(DescriptorMatcher.FLANNBASED);
        /**
         * knnMatch方法的作用就是在给定特征描述集合中寻找最佳匹配
         * 使用KNN-matching算法，令K=2，则每个match得到两个最接近的descriptor，然后计算最接近距离和次接近距离之间的比值，当比值大于既定值时，才作为最终match。
         */
        descriptorMatcher.knnMatch(templateDescriptors, originalDescriptors, matches, 2);

        //System.out.println("计算匹配结果");
        LinkedList<DMatch> goodMatchesList = new LinkedList();

        //对匹配结果进行筛选，依据distance进行筛选
        matches.forEach(match -> {
            DMatch[] dmatcharray = match.toArray();
            DMatch m1 = dmatcharray[0];
            DMatch m2 = dmatcharray[1];

            if (m1.distance <= m2.distance * confidence) {
                goodMatchesList.addLast(m1);
            }
        });
        int matchesPointCount = goodMatchesList.size();
        System.out.println(("通过阈值:"+ passCount +" 当前特征点: "+ matchesPointCount+"个") + (matchesPointCount>=passCount ? " 通过":"不通过"));
        return matchesPointCount>=passCount ;
    }
}
